private import base;
private import strings;


private  
__locked_v is 1_;
private
__unlocked_v is 0_;

type spin_lock is spin_lock {
  locked has type atomic_int;
}

mk_spin_lock has type () => spin_lock
mk_spin_lock() is spin_lock {
  locked = atomic_int(__unlocked_v);
}

spinLock has type action(spin_lock)
spinLock(l) do {
  -- it's usually better to first try with a normal memory read, and then with the CAS
  var success := false;
  while not success do {
    -- yield while locked
    while (__integer_eq(__atomic_int_reference(l.locked), __locked_v)) do {
	    __yield();
    }
    -- try to lock
    case __atomic_int_test_n_set(l.locked, __unlocked_v, __locked_v) in {
      true do { success := true }
      false do { nothing } -- try again
    }
  }
}

spinUnlock has type action(spin_lock)
spinUnlock(l) do {
  __atomic_int_assign(l.locked, __unlocked_v);
}